﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace ModEngine
{
    public class Core
    {
        public delegate void StringArgHandler(string arg1);
        public delegate void NoArgsHandler();
        public delegate void moduleArgsHandler(IModule module);
        public delegate void ExceptionArgHandler(Exception e, string message);

        public event StringArgHandler BeginLoadModuleEvent = delegate { };
        public event moduleArgsHandler LoadModuleEvent = delegate { };
        public event NoArgsHandler EndLoadModuleEvent = delegate { };
        public event ExceptionArgHandler RaiseExceptionEvent = delegate { };

        /// <summary>
        /// Traitement des erreurs lors du traitement des evenements
        /// </summary>
        /// <param name="e">Exception recupéré</param>
        /// <param name="libelleEvenement">Nom de l'evenement</param>
        public void RaiseException(Exception e, string EventName) {
            RaiseExceptionEvent.Invoke(e, EventName);
        }

        private volatile StreamWriter logError = new StreamWriter("error.log", true);
        
        private void onRaiseException(Exception e, string EventName)
        {
            lock(logError){
                logError.WriteLine("{0} {1}", EventName, DateTime.Now.ToLongTimeString());
                logError.WriteLine("{0}", e);
            }
        }

        private List<IModule> modules = new List<IModule>();

        public void BeginLoadModule(String fileName)
        {
            RaiseExceptionEvent += onRaiseException;
            BeginLoadModuleEvent.Invoke(fileName);
            DirectoryInfo directory = new DirectoryInfo(fileName);
            
            if (directory.Exists)
            {
                foreach (FileInfo file in directory.GetFiles("*.Mod.dll"))
                {
                    Assembly moduleAssembly = Assembly.LoadFile(file.FullName);
                    Type[] types = moduleAssembly.GetTypes();
                    foreach (Type type in types)
                    {
                        if (type.GetInterface("IModule") != null)
                        {
                            /* Create a new instance of the 'Module'. */
                            IModule module = (IModule)Activator.CreateInstance(type);
                            modules.Add(module);
                            LoadModuleEvent(module);
                        }
                    }
                }
            }
            
            EndLoadModuleEvent.Invoke();
        }

        public void Dispose()
        {
            foreach (IModule module in modules) {
                try
                {
                    module.Dispose();
                }
                catch (Exception e){
                    RaiseException(e, "Dispose");
                }
            }

            logError.Close();
        }
    }
}

